Lambda(Go)で猫のエネルギー供給量を計算するAPIを作ってAPI Gatewayでテストしてみた
こんにちは、ゲームソリューショングループのsoraです。
今回は、Lambda(Go)で猫の1日当たりのエネルギー供給量を計算するAPIを作って、API Gatewayでテストしてみたことについて書いていきます。
ちなみに、API Gatewayを使わずともLambda上でテストも可能です。
今回はあえて無駄にAPI Gatewayを使用します。
Lambdaで使用するコード(Go)
Goソースコード
猫の体重と生後何か月かを与えると、猫の1日の食事量(kcal)の計算をしてくれる関数です。
計算式についてはあくまで参考程度でお願いいたします。
LambdaでGoを使用するときは、6行目のGo用のLambdaプログラミングモデルをimportする必要があります。
package main import ( "fmt" // Go用のLambdaプログラミングモデル "github.com/aws/aws-lambda-go/lambda" ) type GetData struct { Weight float32 `json:"Weight"` Month int `json:"Month"` } type ReturnData struct { Answer string `json:"Answer"` } func CatCalAPI(event GetData) (ReturnData, error) { var per float32 = 30 * event.Weight + 70 switch { case event.Month <= 4: var kcal float32 = per * 3.0 return ReturnData{Answer: fmt.Sprintf("%.1f kcal", kcal)},nil case event.Month <= 6: kcal := per * 2.5 return ReturnData{Answer: fmt.Sprintf("%.1f kcal", kcal)},nil case event.Month <= 12: kcal := per * 2.0 return ReturnData{Answer: fmt.Sprintf("%.1f kcal", kcal)},nil case event.Month <= 95: kcal := per * 1.2 return ReturnData{Answer: fmt.Sprintf("%.1f kcal", kcal)},nil case event.Month > 95 : kcal := per * 1.1 return ReturnData{Answer: fmt.Sprintf("%.1f kcal", kcal)},nil default : return ReturnData{Answer: fmt.Sprintf("error")},nil } } func main() { lambda.Start(CatCalAPI) }
作成したGoファイルのビルド
GoファイルをLambdaに持っていく前に、ビルドをする必要があります。
Terraformでlocal-execを使ってビルドコマンドもまとめることもできますが、今回は手動で実施します。
Terraformにまとめたい方は以下ページを参考にしてください。
GolangのLambda関数をTerraformだけでデプロイする
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o api
ビルドが終わったら、apiという名前のファイルができています。
LambdaとAPI Gatewayの作成
Terraformソースコード
AWS側で必要なサービスを作成していきます。
私は最近CDKと仲違いしたため、Terraformを使って作成します。
terraform { #AWSプロバイダーのバージョン指定 required_providers { aws = { source = "hashicorp/aws" version = "~> 4.51.0" } } #tfstateファイルをS3に配置する(配置先のS3は事前に作成済み) backend s3 { bucket = "sora-tfstate-bucket" region = "ap-northeast-1" key = "tf-test.tfstate" } } #AWSプロバイダーの定義 provider aws { region = "ap-northeast-1" } #Lambda用IAMロールの信頼関係の定義 data aws_iam_policy_document assume_role { statement { effect = "Allow" principals { type = "Service" identifiers = ["lambda.amazonaws.com"] } actions = ["sts:AssumeRole"] } } #Lambda用IAMロールの作成 resource aws_iam_role iam_for_lambda { name = "CatAPI_Lambda_Role" assume_role_policy = data.aws_iam_policy_document.assume_role.json } #Lambdaへの配置ファイルのzip化 data archive_file lambda { type = "zip" source_file = "../api/api" output_path = "handler.zip" } #Lambdaの作成 resource aws_lambda_function CatAPI_Lambda { filename = "handler.zip" function_name = "CatAPI_Lambda" role = aws_iam_role.iam_for_lambda.arn handler = "api" source_code_hash = data.archive_file.lambda.output_base64sha256 runtime = "go1.x" } #API Gatewayの作成 ##APIの作成 resource aws_api_gateway_rest_api CatAPIGateway { name = "CatAPIGateway" endpoint_configuration { types = ["REGIONAL"] } } ##リソースの作成 resource aws_api_gateway_resource CatAPIResource { rest_api_id = aws_api_gateway_rest_api.CatAPIGateway.id parent_id = aws_api_gateway_rest_api.CatAPIGateway.root_resource_id path_part = "resource" } ##メソッドの作成 resource aws_api_gateway_method CatAPIMethod { rest_api_id = aws_api_gateway_rest_api.CatAPIGateway.id resource_id = aws_api_gateway_resource.CatAPIResource.id http_method = "GET" authorization = "NONE" request_parameters = { "method.request.querystring.Weight" = true "method.request.querystring.Month" = true } } ##リクエスト統合の作成 resource aws_api_gateway_integration CatAPIIntegration { rest_api_id = aws_api_gateway_rest_api.CatAPIGateway.id resource_id = aws_api_gateway_resource.CatAPIResource.id http_method = aws_api_gateway_method.CatAPIMethod.http_method integration_http_method = "POST" type = "AWS" uri = aws_lambda_function.CatAPI_Lambda.invoke_arn request_templates = { "application/json" = <<-EOT { "Weight": $input.params('Weight'), "Month": $input.params('Month') } EOT } } ##レスポンスメソッドの作成 resource aws_api_gateway_method_response CatAPIResponse { rest_api_id = aws_api_gateway_rest_api.CatAPIGateway.id resource_id = aws_api_gateway_resource.CatAPIResource.id http_method = aws_api_gateway_method.CatAPIMethod.http_method status_code = "200" response_models = { "application/json" = "Empty" } } ##レスポンス統合の作成 resource aws_api_gateway_integration_response CatAPIResponseIntegration { rest_api_id = aws_api_gateway_rest_api.CatAPIGateway.id resource_id = aws_api_gateway_resource.CatAPIResource.id http_method = aws_api_gateway_method.CatAPIMethod.http_method status_code = aws_api_gateway_method_response.CatAPIResponse.status_code }
41行目のarchive_fileで先ほどビルドして生成したファイルをzip化しています。
猫の体重(kg)を指すWeightと猫の生後何か月かを指すMonthの2つの値を与える必要があるため、API Gatewayのメソッドリクエストで必須パラメータとしています。
デプロイ
作成したTerraformのコードを実行して構築します。
CDKであればdeployですが、Terraformはapplyなのは間違えがちです。
terraform init terraform apply
LambdaとAPI Gatewayを確認すると、正常に構築できていることが確認できます。
API Gatewayでのテスト
構築できたのでAPI Gatewayでテストしていきます。
私の飼っている猫は生後3か月で体重1kgのため、Month=3&Weight=1
とします。
レスポンス本文のところに、猫の1日の食事量(kcal)が表示されています。
最後に
今回は、Lambda(Go)で猫の1日当たりのエネルギー供給量を計算するAPIを作って、API Gatewayでテストしてみたことを記事にしました。
どなたかの参考になると幸いです。